import json
import os
import Moving
from config import *
from util_pos_ import *
from Planer import *
from Bubble import *
from sampleMap import *
import sampleMap
import sys
from mapElem import *
from Env import *

event_queue = []
key_hold = []
build_map = {}
bubble_current_id = 0
add_library('sound')
imgs = {}
imgs_tab = {}
imgs_dlg = {}
w, h = 800, 600
bar_x = 140
bar_interval_x = 110
bar_y = 0

tmp_map_index = -1
# 右下角坐标
corner_x = 435
corner_interval_x = 54
corner_y = 535

tab_x = 30
tab_interval_x = 60
tab_y = 70

room_x = 29
room_interval_x = 195
room_interval_y = 113
room_y = 105

bg_room_x = 25
bg_room_interval_x = 120
bg_room_interval_y = 265
bg_room_y = 83

bag_x, bag_y = (529, 378)
start_btn_x, start_btn_y = 545, 537
my_state = {'bubbles': []}
my_state['bubbles_obj'] = []
bubble_range_r = {}
chara_page2 = []

bots = []
target_pool = []
# global_dict
resource_sound = {}
bots_moving_obj = []
bots_moving_obj_dict = {}
winbgm = None
bubble_log = []
global_sections_for_all = {}
display_section_for_all = {}
menu_state = {'state': ''}
global_map_data = {}


def get_obs_from_mapdata(mapdata):
    obs = []
    for row in range(13):
        for col in range(15):
            elem = mapdata[row][col]
            if mapdata[row][col] > 0 and qqtMapElems[elem].canMove == 0:
                obs.append((col, row))
    return obs


def get_obs():
    if game_state['ui_state'] != '2':
        return []
    global global_map_data
    mapdata = global_map_data['foreMapElems']
    a = get_obs_from_mapdata(mapdata)
    b = get_obs_from_mapdata(global_map_data['backMapElems'])
    return a + b


def update_bot(bot):
    p = bot['position']
    bots_moving_obj_dict[bot['id']].update(p.x, p.y, bot['player_state']['current_direction'])


def update_me(bot):
    p = bot['pos']
    bots_moving_obj_dict[-1].update(p.x, p.y, bot['player_state']['current_direction'])


bots_dict = {}
bot_img = {'left': [], 'right': [], 'up': [], 'down': []}
character_gifs = {}


# register_walk_pic

def get_current_obs():
    global global_map_data
    mapdata = global_map_data['foreMapElems']
    return get_obs_from_mapdata(mapdata)


def remove_current_obs(obs):
    global global_map_data
    mapdata = global_map_data['foreMapElems']
    for x, y in obs:
        mapdata[y][x] = 0


def get_range_of_bubble(bubble):
    return 3
    # return bubble_range_r[bubble]


def add_bubble_radius(bubble, r):
    bubble_range_r[bubble] = r


def normal_character_state():
    d = {}
    for k in [key_number, key_power, key_speed]:
        d[k] = [2, 10]
    return d


def get_speed(bot):
    if 'character_state' not in bot:
        return 3
    return min(bot['character_state'][key_speed][-1],
               bot['character_state'][key_speed][0] + bot['player_state']['obj']['speed'])


def get_number(bot):
    if 'character_state' not in bot:
        return 3
    return min(bot['character_state'][key_number][0] + bot['player_state']['obj']['number'],
               bot['character_state'][key_number][1])


def get_power(bot):
    if 'character_state' not in bot:
        return 3
    return min(bot['character_state'][key_power][-1],
               bot['character_state'][key_power][0] + bot['player_state']['obj']['power']) + 1


def is_chara_has_bubble(bot):
    return len(bot['bubbles']) < get_number(bot)


self_state = {'pos': None, 'state': 'alive', 'bubbles': [], 'character_state': normal_character_state(),
              'player_state': new_player_state()}
my_state = self_state


def new_self_state():
    new_state = {'pos': None, 'bubbles': [], 'character_state': normal_character_state(),
                 'player_state': new_player_state()}

    return new_state


playerIcon = {}
game_state = {'player_moving_range': (15, 13), 'character_py': 'hy', 'page_number': 1, 'current_map': '',
              'ui_state': '1', 'player': 11, 'current_direction': 'down', 'bubble_index': 3, 'bubble_gif_index': 0,
              'flame': 0, 'is_pressed': True, 'show_back': True, 'show_fore': True}

bubble_time = {}

global_map = {}
finish_bomb = []

position_object = {'number': [], 'speed': [], 'power': []}


def update_bubble_gif():
    game_state['bubble_gif_index'] = (game_state['bubble_gif_index'] + 1) % 4


bigIconImgs = {}
bigIconNames = 'bomb|box|bun|desert|field|machine|match|mine|pig|pve|rand|sculpture|snow|tank|town|treasure|water'.split(
    '|')


def sample(us):
    return us[int(random(0, len(us)))]


game_state['bigIconNames_begin'] = []
# bigIconNames_begin = [sample(bigIconNames) for i in range(8)]
player_walk = {}
player_bubble = {}
imgs_char = {}

me = PVector(91, 147)
self_state['pos'] = me
me_gif_index = PVector(0, 0)

room_buttons = []
room_start_return = []

RectButton_cache = {}
function_cache = {}
character_moving_gif = {}
for c in character_py_names:
    character_moving_gif[c] = {}

bgm = None
bgm2 = None

# 房间
# 动图

imgs_btn = {}
imgs_btn_state00 = {}
gif_cache = {}
gif_obj_cache = {}


class Gif:
    def __init__(self, x, y, img_name):
        self.topleft = PVector(x, y)
        self.img_name = img_name
        self.start_time = None
        self.tick_time = 125
        self.is_loop = False
        self.cur_i = 0
        self.is_end = False

    @staticmethod
    def load_gif(img_name, number, file_name):
        gif_cache[img_name] = [loadImage(file_name.format(i)) for i in range(number)]
        assert gif_cache[img_name][0] is not None

    @staticmethod
    def save_exist_gif(img_name, images):
        gif_cache[img_name] = images
        for i in images:
            assert i is not None

    def is_not_start(self):
        return self.start_time is None

    def start(self):
        if self.start_time is None:
            self.start_time = millis()

    def get_current_index(self):
        return self.cur_i

    def is_over(self):
        return self.cur_i == len(gif_cache[self.img_name]) - 1

    def get_current_frame(self):
        if self.is_not_start():
            return gif_cache[self.img_name][0]
        cur = millis()
        i = (cur - self.start_time) / self.tick_time
        # print('num tick ',i,cur,self.start_time)
        i = int(i)
        if self.is_loop:
            i = i % len(gif_cache[self.img_name])
        else:
            i = min(len(gif_cache[self.img_name]) - 1, i)
            if i == len(gif_cache[self.img_name]) - 1:
                self.is_end = True
        self.cur_i = i
        return gif_cache[self.img_name][i]


class BubbleGif(Gif):
    def __init__(self, x, y, img_name):
        self.topleft = PVector(x, y)
        self.img_name = img_name
        self.start_time = None
        self.tick_time = 125
        self.is_loop = True
        self.cur_i = 0


class Image:
    def __init__(self, x, y, img_name):
        self.topleft = PVector(x, y)
        self.img_name = img_name
        self.isClicked = False
        self.button_i = 11
        self.name = ''

    def collide_with_point(self, p):
        x, y = p
        if self.topleft.x < x < self.topleft.x + imgs_btn[self.img_name][0].width:
            if self.topleft.y < y < self.topleft.y + imgs_btn[self.img_name][0].height:
                return True
        return False

    def get_image(self):
        return imgs_btn[self.img_name][2]

    def get_pending_image(self):
        return imgs_btn[self.img_name][1]

    def get_clicked_image(self):
        return imgs_btn[self.img_name][0]

    def update_with_mouse(self, mouse_p, mp):
        if self.collide_with_point(mouse_p):
            if mp:
                self.isClicked = True
                game_state['player'] = self.character_i
                # self_state ={'character_state':None,'player_state': new_player_state()}

                return True
        return False

    def draw_img(self, img):
        image(img, self.topleft[0], self.topleft[1])


class RectButton:
    def __init__(self, x, y, w, h, name):
        '''

        :param x: topleft
        :param y:
        :param name: 名字
        '''
        self.topleft = PVector(x, y)
        self.isClicked = False
        self.button_i = 11
        self.name = name
        self.disable = False
        self.queue = event_queue
        self.height = h
        self.width = w

    def collide_with_point(self, p):
        x, y = p
        if self.topleft.x < x < self.topleft.x + self.width:
            if self.topleft.y < y < self.topleft.y + self.height:
                return True
        return False

    def update_with_mouse(self, mouse_p, mp):
        if self.collide_with_point(mouse_p):
            if mp:
                self.isClicked = True
                self.queue.append(self.name)
                delay(200)
                return True
        return False

    def show(self, rect_fun):
        rect_fun(self.x, self.y, self.width, self.height)


class Button:
    def __init__(self, x, y, img_name, imgs_btn_=imgs_btn):
        self.topleft = PVector(x, y)
        self.img_name = img_name
        self.isClicked = False
        self.button_i = 11
        self.name = ''
        self.disable = False
        self.imgs_btn_ = imgs_btn_

    def collide_with_point(self, p):
        x, y = p
        if self.topleft.x < x < self.topleft.x + self.imgs_btn_[self.img_name][0].width:
            if self.topleft.y < y < self.topleft.y + self.imgs_btn_[self.img_name][0].height:
                return True
        return False

    def get_image(self):
        return self.imgs_btn_[self.img_name][2]

    def get_pending_image(self):
        return self.imgs_btn_[self.img_name][1]

    def get_clicked_image(self):
        return self.imgs_btn_[self.img_name][0]

    def update_with_mouse(self, mouse_p, mp):
        if self.collide_with_point(mouse_p):
            if mp:
                if not game_state['is_pressed']:
                    self.isClicked = True
                    game_state['is_pressed'] = True
                    delay(200)
                    return True
        return False

    def draw_img(self, img):

        image(img, self.topleft[0], self.topleft[1])

    def show_with_mouse(self, mouse_p, mp):

        if not self.collide_with_point(mouse_p):
            self.draw_img(self.get_image())
        elif mp:

            if not game_state['is_pressed']:

                self.draw_img(self.get_clicked_image())
                if not self.disable:
                    self.isClicked = True
                    game_state['is_pressed'] = True
                    delay(200)
        else:

            self.draw_img(self.get_pending_image())


class Character:
    def __init__(self, x, y, img_name):
        self.topleft = PVector(x, y)
        self.img_name = img_name
        self.isClicked = False
        self.disable = False
        self.character_i = 11
        self.name = ''

    def collide_with_point(self, p):
        x, y = p
        if self.topleft.x < x < self.topleft.x + playerIcon[self.img_name].width:
            if self.topleft.y < y < self.topleft.y + playerIcon[self.img_name].height:
                return True
        return False

    def get_py_name(self):
        # get pinyin name by zh name
        print('selfanme m', unicode(self.name, 'utf-8'))
        return character_names2py.get(self.name, None)

    def get_py_name_by_name(self):
        return self.get_py_name()
        # return self.name.split('_')[-1]        

    def get_char_img(self):
        name = self.get_py_name()
        print('pyname', name)
        return imgs_char.get(name)

    def get_stat(self):
        assert self.name in player
        return player.get(self.name, {})

    def get_image(self):
        return playerIcon[self.img_name]

    def show_image(self):
        img = playerIcon[self.img_name]
        image(img, self.topleft.x, self.topleft.y)

    def get_name_image(self):
        name = self.get_py_name()
        return imgs_char['name_' + name]

    def show_name_image(self):
        image(self.get_name_image(), 523, 96)

    def show_char_image(self):
        if not self.get_char_img():
            return
            # (767, 210)
        image(self.get_char_img(), 767 - self.get_char_img().width, 210 - self.get_char_img().height)
        return True

    def show_above_ui(self):
        a = self.show_char_image()
        if not a:
            print('show ui return')
            return
        image(imgs_dlg['roleProp'], statist_topleft[0], statist_topleft[1])

        x = statist_topleft[0] + 34
        fill(255, 255, 0)
        rect(x, statist_topleft[1] + 13, 110 * player[self.name]['糖果'][0] / 10, 15)

        fill(255, 255, 0, 100)
        rect(x, statist_topleft[1] + 13, 110 * player[self.name]['糖果'][1] / 10, 15)

        fill(255, 132, 51)
        rect(x, statist_topleft[1] + 31, 110 * player[self.name]['威力'][0] / 10, 15)
        fill(255, 132, 51, 100)
        rect(x, statist_topleft[1] + 31, 110 * player[self.name]['威力'][1] / 10, 15)

        fill(71, 209, 71)
        rect(x, statist_topleft[1] + 48, 110 * player[self.name]['速度'][0] / 10, 15)
        fill(71, 209, 71, 100)
        rect(x, statist_topleft[1] + 48, 110 * player[self.name]['速度'][1] / 10, 15)

        self.show_image()
        self.show_name_image()

    def show_with_mouse(self, mouse_p):
        if menu_state['state'] == '':
            if not self.collide_with_point(mouse_p):
                if self.isClicked:
                    self.show_image()
                else:
                    self.show_image()
                    fill(0, 100)
                    w = self.get_image().width
                    rect(self.topleft.x, self.topleft.y, w, w)
            else:

                self.show_above_ui()
        else:
            self.show_image()

    def update_with_mouse(self, mouse_p, mp):
        if self.collide_with_point(mouse_p):
            if mp:
                if not self.disable:
                    self.isClicked = True
                    game_state['player'] = self.character_i
                    game_state['character_py'] = self.get_py_name_by_name()

                    self_state['character_state'] = get_character_all_attributes(self.character_i)

                    return True
        return False


imgs_map = {}
btn_imgs = {}
flame = {}
flame_gif_index = {}
chara_page1 = []
chara_page3 = []
imgs_elem = {}
btn_cache = {}
btn_cache_state0 = {}
bot_i = 0


def add_mile(s):
    global player
    player['s'] += s


def get_mile():
    global player
    return player['s']


def get_walk_img_i():
    s = get_mile()
    s = int(s / 8)
    return s % 4


def add_bot_mile(bot, s):
    bot['player_state']['s'] += s


def get_bot_mile(bot):
    return bot['player_state']['s']


def get_bot_walk_img_i(bot):
    s = get_bot_mile(bot)
    s = int(s / 8)
    return s % 4


def get_bot_img(bot):
    global bot_img
    dir = bot['player_state']['current_direction']
    walk_img_i = get_bot_walk_img_i(bot)
    return bot_img[dir][walk_img_i]


def new_bot():
    p = PVector(320, 300)
    d = {'id': bot_i, 'position': p, 'state': 'alive', 'target': None, 'bubbles': [],
         'player_state': new_player_state()}
    global bot_i
    bot_i += 1
    return d


def bot_add_obj(bot, obj):
    bot['player_state']['obj'][obj] += 1
    return bot


def get_bot_bubble_limit():
    return 1


def bot_put_bubble(bot_dict, p):
    if len(bot_dict['bubbles']) < 122:  # get_bot_bubble_limit():
        if p not in bubble_time:
            # bubble_log[p] = True

            bot_dict['bubbles'].append(p)
            bubble_time[p] = millis()
            flame_gif_index[p] = 0
            # bubble_power[p] = bot_dict['player_state']['obj']['power'] + 2


def boom_hit_player(boom, p_bot):
    # boom   topleft
    # p bot vector
    x, y = boom
    if abs(x - p_bot.x) < 20 and abs(y - p_bot.y) < 20:
        return True
    return False


def bots_bubble(boom):
    for bot in bots:
        p_bot = bot['position']
        if boom_hit_player(boom, p_bot):
            bot['state'] = 'Dead!'
            for obj, num in bot['obj'].items():
                x_r = random(0, w)
                y_r = random(0, h)
                x_r, y_r = get_grid_idx(x_r, y_r)
                position_object[obj].append((x_r, y_r))
    return


def bots_bubble_grid(boom):
    c, r = boom
    y, x = get_grid_centre(r, c)
    bots_bubble((x, y))


sound = {}


def setup():
    size(w, h)
    frameRate(30)
    function_cache['timer'] = Timer()
    global bgm
    bgm = SoundFile(this, 'bgm.mp3')
    global bgm2
    bgm2 = SoundFile(this, 'M15.mp3')
    bgm2.amp(0.03)
    bgm.amp(0.03)
    bgm.loop()
    sound['bgm'] = bgm
    global winbgm
    winbgm = SoundFile(this, 'PlayerWin.mp3')
    global losebgm
    losebgm = SoundFile(this, 'loseGame.mp3')

    RectButton_cache['last_page'] = RectButton(521, 212, 20, 110, 'last_page')
    RectButton_cache['next_page'] = RectButton(770, 213, 20, 110, 'next_page')

 
    for py in character_py_names:
        playD = dict()
        for i in range(6):
            d = {'left': 2, 'right': 3, 'up': 1, 'down': 0}
            if 'yy' in py or 'xq' in py or 'cl' in py or 'hy' in py or 'mly' in py or 'hwz' in py or 'wll' in py:
                d = {'left': 2, 'right': 3, 'up': 0, 'down': 1}
            if 'yy' in py:
                d = {'left': 1, 'right': 3, 'up': 0, 'down': 2}
            if 'kl' in py:
                d = {'left': 3, 'right': 2, 'up': 1, 'down': 0}
            if 'nz' in py :
                d = {'left': 3, 'right': 2, 'up': 1, 'down': 0}
            for direct, v in d.items():
                img = loadImage('walk/{}/{}_{}_{}.png'.format(py, py, v, i))
                playD[direct] = playD.get(direct, []) + [img]
        player_walk[py] = playD
    # ui1
    imgs['selectRoom'] = loadImage('bg_selRoom_0_0.png')

    # 上面导航
    names = ['sociality', 'task', 'member', 'info', 'pet', 'menu']
    for ui_name in names:
        imgs[ui_name] = loadImage('btn_{}_0_2.png'.format(ui_name))

    # 角落按钮

    def get_btn_3_img(ui_name):
        return [loadImage('btn_{}_0_{}.png'.format(ui_name, i)) for i in range(3)]

    names = ['shop', 'practice', 'quickJoin', 'createRoom', 'match']
    j = 0
    for ui_name in names:

        imgs_btn_state00[ui_name] = get_btn_3_img(ui_name)
        assert imgs_btn_state00[ui_name] != [None, None, None]
        px, py = corner_x + 18 + corner_interval_x * j, corner_y
        assert ui_name not in btn_cache
        if j == 0:
            btn_cache_state0[ui_name] = Button(corner_x, corner_y, ui_name, imgs_btn_state00)
        else:
            btn_cache_state0[ui_name] = Button(px, py, ui_name, imgs_btn_state00)

        print('btn', btn_cache_state0[ui_name].topleft)
        j += 1
    imgs['room'] = loadImage('dlg_room_0_2.png')
    # 竞技 探索 聊天
    names = ['compete', 'explore', 'chat']
    for ui_name in names:
        imgs[ui_name] = [loadImage('tab_{}_0_0.png'.format(ui_name)), loadImage('tab_{}_0_1.png'.format(ui_name))]
    # 无道具 道具 抢宝
    names = ['noItem', 'item', 'honor']
    for ui_name in names:
        imgs[ui_name] = loadImage('tab_{}_0_0.png'.format(ui_name))

    for mapIcon in bigIconNames:
        bigIconImgs[mapIcon] = loadImage('bigIcon/{}_0_0.png'.format(mapIcon))
        if bigIconImgs[mapIcon] is None:
            print('X')
            # ui 2

    imgs['bgRoom'] = loadImage('bg_room_0_0.png')
    imgs['bgGame'] = loadImage('bg_game.png')
    imgs['number'] = loadImage('item1_stand_0_0.png')
    imgs['power'] = loadImage('item2_stand_0_0.png')
    imgs['speed'] = loadImage('item3_stand_0_0.png')
    # 人物背景
    names = ['playerDown', 'playerUp']
    for ui_name in names:
        imgs[ui_name] = loadImage('room/btn_{}_0_0.png'.format(ui_name))
    # 右上角
    names = ['selMode', 'roomProp', 'selMap'] + ['storage', 'start', 'return']
    for ui_name in names:
        if ui_name == 'start':
            imgs[ui_name] = loadImage('room/btn_{}_0_3.png'.format(ui_name))
        else:
            imgs[ui_name] = loadImage('room/btn_{}_0_2.png'.format(ui_name))
    for ui_name in ['selMode', 'roomProp', 'selMap']:
        imgs_btn[ui_name] = [loadImage('room/btn_{}_0_{}.png'.format(ui_name, i)) for i in range(4)]
    x, y = room_button_topleft
    for ix, name in enumerate(['selMode', 'roomProp', 'selMap']):
        room_buttons.append(Button(x, y + room_button_interval_y * ix, name))

    def load_image_list(ui_name, dir, num=4):
        return [loadImage(dir + '/btn_{}_0_{}.png'.format(ui_name, i)) for i in range(num)]

    # 载入模式
    for i, n in enumerate(map_mode_list):
        imgs_btn[n] = load_image_list(n, 'room/map/', num=1) * 4
        assert imgs_btn[n][0] is not None
        x, y = map_sel_item_topleft
        px, py = x, y + imgs_btn[n][0].height * i
        btn_cache[n] = Button(px, py, n)

    for n in ['start', 'return']:
        px, py = btn_pos[n]
        btn_cache[n] = Button(px, py, n)
        imgs_btn[n] = load_image_list(n, 'room')
        assert imgs_btn[n][0] is not None
        # 游戏内u
    for n in ['saveReplay', 'leavegame']:
        px, py = btn_pos[n]
        btn_cache[n] = Button(px, py, n)
        name2dir = {'saveReplay': 'game', 'leavegame': 'common'}
        imgs_btn[n] = load_image_list(n, name2dir[n])
        print(n)
        assert imgs_btn[n][0] is not None

        # 游戏内ui 图片
    for n in img_pos.keys():
        imgs[n] = loadImage('game/{}_0_0.png'.format(n))
        assert imgs[n] is not None
    # 游戏ui 按钮
    resource_sound['attrack'] = SoundFile(this, 'sound/X12_01.wav')
    btn_cache['start'].disable = True
    btn_imgs['cancel'] = loadImage('common/btn_{}_0_3.png'.format('cancel'))
    btn_imgs['confirm'] = loadImage('common/btn_{}_0_3.png'.format('confirm'))

    x, y = room_button_topleft
    # 选地图
    for ui_name, p in zip(['confirm', 'cancel'], [map_sel_confirm, map_sel_back]):
        imgs_btn[ui_name] = load_image_list(ui_name, 'common')
        obj = Button(p[0], p[1], ui_name)

        room_start_return.append(obj)
    # 人物选择
    global playerIcon
    for name in allcharacters:
        playerIcon[name] = loadImage('playerIcon/{}.jpg'.format(name))

    for name in character_py_names:
        imgs_char[name] = loadImage('room/char/{}_0_0.png'.format(name))

        assert imgs_char[name] is not None
    for name in character_py_names:
        # name_kl_0_0.png
        imgs_char['name_' + name] = loadImage('room/char/name_{}_0_0.png'.format(name))
        assert imgs_char['name_' + name] is not None
    data = [None] + allcharacters
    px, py = (548, 212)
    # global playerIcon
    names = '19_kl|20_nz|21_wll|22_yy'.split('|')
    for i, name in enumerate(names):
        img = playerIcon[name]
        p = (px + img.width * i, py)
        ch = Character(p[0], p[1], name)
        ch.name = character_names[-4:][i]
        chara_page3.append(ch)
    for i, name in enumerate(data):
        if i > 7:
            if name:
                if i > 15:
                    chara_page2.append(None)
                    continue
                img = playerIcon[name]
                i_ = i - 8
                c, r = i_ % 4, int(i_ / 4)
                p = (px + img.width * c, py + img.width * r)
                ch = Character(p[0], p[1], name)

                ch.character_i = [11, 11, 11, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 22, 22][i]
                ch.name = character_names[i - 1]
                chara_page2.append(ch)

            else:
                chara_page2.append(None)
        else:
            if name:
                img = playerIcon[name]
                c, r = i % 4, int(i / 4)
                p = (px + img.width * c, py + img.width * r)
                ch = Character(p[0], p[1], name)
                ch.character_i = [11, 11, 11, 11, 12, 13, 14, 15][i]
                ch.name = character_names[i - 1]
                if i in [0, 1, 2]:
                    ch.disable = True
                chara_page1.append(ch)

            else:
                chara_page1.append(None)

    # 泡泡爆开
    Gif.load_gif('misc111_stand', 5, 'misc/misc111_stand_0_{}.png')
    Gif.load_gif('misc111_trigger', 13, 'misc/misc111_trigger_0_{}.png')
    # 泡泡弹弹弹
    for bubbleIndex in [299, 300, 301, 302, 3, 6, 7, 18, 19, 20]:
        for i in range(4):
            img = loadImage('bomb/bomb{}_stand_0_{}.png'.format(bubbleIndex, i))
            player_bubble[bubbleIndex] = player_bubble.get(bubbleIndex, []) + [img]
            assert img is not None
        imgs_ = player_bubble[bubbleIndex][:]
        Gif.save_exist_gif('player_bubble' + str(bubbleIndex), imgs_)
    # 火焰
    flame['middle'] = [loadImage('flame/flame1_stand_0_{}.png'.format(i)) for i in range(4)]
    Gif.save_exist_gif('flame_middle', flame['middle'])
    for k, v in {'left': 4, 'right': 2, 'up': 3, 'down': 5}.items():
        flame[k] = [loadImage('flame/flame{}_stand_0_{}.png'.format(v, i)) for i in range(7)]
        Gif.save_exist_gif('flame_' + k, flame[k])
        # 统一存储位置

    imgs_dlg['roleProp'] = loadImage('room/char/dlg_roleAttr_0_0.png')
    imgs_dlg['selMap'] = loadImage('room/dlg_selMap_0_0.png')

    imgs_map['match01'] = loadImage('map/match01_2_0_0.png')
    imgs_map['match02'] = loadImage('map/match02_2_0_0.png')
    imgs_map['match03'] = loadImage('map/match03_4_0_0.png')
    for name in map_mode_list:
        for i in [2, 4, 6, 8]:
            if name == 'rand':
                # rand_0_0.png
                img_ = loadImage('map/{}_0_0.png'.format(name))
            else:
                img_ = loadImage('map/{}01_{}_0_0.png'.format(name, i))
            if img_:
                imgs_map[name + '01'] = img_
                break
    assert imgs_map['match01'] is not None

    # 地图
    for n in map_mode_list[1:]:
        print('loading', n)
        imgs_elem[n] = {}

        for i in range(200):
            if os.path.exists('/Users/xyh/Documents/Processing/qqui/data/mapElem/{}/elem{}_stand_0_0.png'.format(n, i)):
                imgs_elem[n][i] = loadImage('mapElem/{}/elem{}_stand_0_0.png'.format(n, i))

    for chara_name in character_py_names:
        character_gifs[chara_name] = {}
        for direction in bot_img.keys():
            for i in range(6):
                directioni = {'left': 2, 'right': 3, 'up': 0, 'down': 1}.get(direction)
                img = loadImage('walk/{}/{}_{}_{}.png'.format(chara_name, chara_name, directioni, i))
                # assert img is not None
                # print(img.width,img.height)#44, 59
                if direction not in character_gifs[chara_name]:
                    character_gifs[chara_name][direction] = []
                character_gifs[chara_name][direction].append(img)

    bot_img.update(character_gifs['hy'])
    # make bot
    n_bot = 1
    for i in range(n_bot):
        bot = new_bot()
        bots.append(bot)
        bots_dict[bot['id']] = bot
        bot_obj = Moving.MovingObj(0, 0)
        bot_obj.register_walk_pic(bot_img)
        bots_moving_obj.append(bot_obj)
        bots_moving_obj_dict[bot['id']] = bot_obj

    bot_obj = Moving.MovingObj(0, 0)
    bot_obj.register_walk_pic(bot_img)
    bots_moving_obj_dict[-1] = bot_obj


def show_top_btn():
    names = ['sociality', 'task', 'member', 'info', 'pet', 'menu']
    for i in range(len(names)):
        name = names[i]
        image(imgs[name], bar_x + bar_interval_x * i, bar_y)


def show_bottom_btn():
    corner = ['shop', 'practice', 'quickJoin', 'createRoom', 'match']
    for i in range(len(corner)):
        name = corner[i]

        btn_cache_state0[name].show_with_mouse((mouseX, mouseY), mousePressed)

        # if i == 0:
        #     image(imgs[name], corner_x + corner_interval_x * i, corner_y)
        # else:
        #     image(imgs[name], corner_x + 18 + corner_interval_x * i, corner_y)
    if btn_cache_state0['createRoom'].isClicked:
        game_state['ui_state'] = '1'
        btn_cache_state0['createRoom'].isClicked = False


def show_mode():
    names = ['compete', 'explore', 'chat']
    for i in range(len(names)):
        name = names[i]
        x, y = tab_x - 10 + (imgs[name][0].width + 4) * i, tab_y - 2 - imgs[name][0].height
        if i == 0:
            image(imgs[name][1], x, y)
        else:
            image(imgs[name][0], x, y)

    names = ['noItem', 'item', 'honor']
    for i in range(len(names)):
        name = names[i]
        image(imgs[name], tab_x + tab_interval_x * i, tab_y)


def show_room():
    for row in range(3):
        for col in range(2):
            image(imgs['room'], room_x + room_interval_x * col, room_y + row * room_interval_y)
            x, y = room_x + 8 + room_interval_x * col, room_y + row * room_interval_y + 38

            image(bigIconImgs[game_state['bigIconNames_begin'][row * 2 + col]], x, y)
            fill(255)
            textSize(16)
            text("00" + str(row * 2 + col), x + 5, y - 15)
            text("0/8", x + 55, y + 45)


# def get_cross_section(pos, r, map_d):
#     '''
#     十字攻击
#     :param pos:
#     :param r:
#     :param map_d:
#     :return:
#     '''
#     bricks = get_current_obs()#[u for u in map_d]

#     x, y = pos
#     brokens = []
#     hitrange = []
#     for dx, dy in [(0, 1), (1, 0), (0, -1), (-1, 0)]:
#         for i in range(0, r):
#             newx, newy = x + dx * i, y + dy * i
#             p = (newx, newy)
#             if p in bricks:
#                 brokens.append(p)
#                 break
#             hitrange.append(p)
#     hitrange.append(p)
#     return list(set(hitrange)), brokens
#     # res = [(x,y+i) for i in range(-r,r+1) ]+[(x+i,y) for i in range(-r,r+1) ]
#     # return list(set(res))             a


def show_player_section():
    for row in range(2):
        for col in range(4):
            if row == 0:
                img = 'playerUp'
            else:
                img = 'playerDown'
            image(imgs[img], bg_room_x + bg_room_interval_x * col, bg_room_y + row * bg_room_interval_y)


def update_trap_state(bot_dict, sections):
    for sx, sy in sections:
        if game_state['ui_state'] == '2':
            # 攻击玩家
            if (sx, sy) in bot_dict:
                for bot in bot_dict[(sx, sy)]:
                    bot['player_state']['trap'] = True
    return


def get_bot_dict(bots_):
    bot_dict = {}
    for bot in bots_:
        if 'position' in bot:
            grid = get_grid_idx(bot['position'].x, bot['position'].y)
        else:
            grid = get_grid_idx(bot['pos'].x, bot['pos'].y)
        if grid not in bot_dict:
            bot_dict[grid] = []
        bot_dict[grid].append(bot)
    return bot_dict


def user_control():
    if key == 'g' and keyPressed:
        me.x, me.y = mouseX, mouseY
    if len(key_hold) > 0:
        key2 = key_hold[-1]
        if key2 in list('asdw'):

            v = get_speed(self_state)
            k2d = {'a': 'left', 'd': 'right', 'w': 'up', 's': 'down'}
            game_state['current_direction'] = k2d[key2]
            self_state['player_state']['current_direction'] = k2d[key2]
            direction = k2d[key2]
            global global_map_data
            if 'foreMapElems' not in global_map_data:
                obs = []
            else:

                mapdata = global_map_data['foreMapElems']

                obs = get_obs_from_mapdata(mapdata)
            fb = [(u.x, u.y) for u in my_state.get('bubbles_obj', [])] + obs  # list(global_map.keys())

            me2 = brick_bubble_player_limit(me, direction, fb, False)
            me.x = me2.x
            me.y = me2.y

            k2dv = {'a': (-v, 0), 'd': (v, 0), 'w': (0, -v), 's': (0, v)}


def set_my_born_point():
    global global_map_data
    mapdata = global_map_data['foreMapElems']
    for y in range(8):
        for x in range(13):
            if (x, y) not in get_obs_from_mapdata(mapdata):
                me.x, me.y = get_grid_centre(x, y, zone_topleft=game_zone)
                return me.x, me.y


def set_bot_point(x_, y_, bot):
    global global_map_data
    mapdata = global_map_data['foreMapElems']
    for y in range(8):
        for x in range(13):
            if (x, y) not in get_obs_from_mapdata(mapdata):

                born_x, born_y = get_grid_centre(x, y, zone_topleft=game_zone)
                if manh(x_, y_, born_x, born_y) > 40 * 8:
                    print('found', x, y)
                    return born_x, born_y
    return x, y


def set_other_point(x, y, bots):
    for bot in bots:
        bot['position'].x, bot['position'].y = set_bot_point(x, y, bot)


def set_born_point(bots):
    '''
    随机选出生点
    :param bots:
    :return:
    '''
    x, y = set_my_born_point()
    print('set my born point', x, y)
    set_other_point(x, y, bots)


def pick_a_brick(other):
    '''
    随机选择方块
    :param other:
    :return:
    '''
    bricks = get_current_obs()  # global_map.keys()
    bricks = [u for u in bricks if u not in other]
    if len(bricks) == 0:
        return None
    r = int(random(0, len(bricks)))
    return bricks[r]


def addTargetOnBot(bot):
    '''
    给机器人加入目标
    :param bot:
    :return:
    '''
    # bot['target']  = (4,4)
    if bot['target']:
        if bot['target'] not in get_obs():
            bot['target'] = None
    if bot['target'] not in get_obs() or not bot['target']:
        brick = pick_a_brick(target_pool)
        if brick:
            botx_grid, boty_grid = get_grid_idx(bot['position'].x, bot['position'].y)
            dir2dxdy = {'left': (-1, 0), 'right': (1, 0), 'up': (0, -1), 'down': (0, 1)}
            for direction, diff in dir2dxdy.items():
                bx, by = brick
                next2brick = bx + diff[0], by + diff[1]
                path_direction = get_dir(bot, botx_grid, boty_grid, next2brick)
                if path_direction:
                    bot['target'] = brick
                    target_pool.append(brick)


def bot_displacement(bot, dx, dy):
    pp = bot['position']
    bot['position'].x, bot['position'].y = pp.x + dx, pp.y + dy

    # pp=brick_bubble_player_limit(pp, dirs[int(r)])
    # bot['position'].x, bot['position'].y = limit_player(pp.x,pp.y)
    return


def get_dir(bot, botx_grid, boty_grid, destination):
    width_range, height_range = game_state['player_moving_range']
    forbids = get_obs()
    tx, ty = destination
    if not 0 <= tx < width_range or not 0 <= ty < height_range:
        return None

    if (botx_grid, boty_grid) == destination:
        pp = bot['position']
        x_centre, y_centre = get_grid_centre_from_x_y(pp.x, pp.y)
        allowed_directions = ['left', 'right', 'up', 'down']
        local_direction = inner_grid_path_planner(pp.x, pp.y, x_centre, y_centre, get_speed(bot), allowed_directions)
        if local_direction:
            dir_i = ['left', 'right', 'up', 'down'].index(local_direction)
            return dir_i
        return None

    paths = Astar_finder((botx_grid, boty_grid), destination, forbids, width_range, height_range)
    if paths == []:
        return None
    if len(paths) < 2:
        return None
    global g_paths
    g_paths = paths

    safex, safey = paths[1]

    next_grid_direction = ''
    if safex < botx_grid:
        next_grid_direction = 'left'

    if safex > botx_grid:
        next_grid_direction = 'right'

    if safey < boty_grid:
        next_grid_direction = 'up'

    if safey > boty_grid:
        next_grid_direction = 'down'
    # if next_grid_direction in ['left','right']:
    allowed_directions = get_other_direction(next_grid_direction)

    pp = bot['position']
    x_centre, y_centre = get_grid_centre_from_x_y(pp.x, pp.y)

    local_direction = inner_grid_path_planner(pp.x, pp.y, x_centre, y_centre, get_speed(bot), allowed_directions)
    if local_direction:
        dir_i = ['left', 'right', 'up', 'down'].index(local_direction)

        return dir_i
    return ['left', 'right', 'up', 'down'].index(next_grid_direction)


# def get_dir(botx_grid,boty_grid,destination):
#     return get_dir_(botx_grid,boty_grid,destination,global_map.keys())

def get_batch_grid(me, bots):
    grid = []
    for bot in bots:
        if bot == me:
            continue
        x, y = get_grid_idx(bot['position'].x, bot['position'].y)
        grid.append((x, y))
    return grid


def bot_attract_other(p, bot, other_bots):
    if any([in_bot_attract_range(p, get_bot_power(bot), (attx, atty)) for attx, atty in
            get_batch_grid(bot, other_bots)]):
        return True
    return False


def bots_move():
    # if random(0,4)<1:
    #     return
    v_ = 2

    player_position = me
    px, py = player_position.x, player_position.y
    global player
    mex, mey = get_grid_idx(px, py)
    for bot in bots:

        if bot != self_state and bot['player_state']['trap'] is True:

            botx_grid, boty_grid = get_grid_idx(bot['position'].x, bot['position'].y)
            if (mex, mey) == (botx_grid, boty_grid):
                bot['state'] = 'Dead!'
                bot['player_state']['trap'] = False
                resource_sound['attrack'].play()
            continue
        if bot['player_state']['isBot'] is False:
            continue

        if not is_bot_alive(bot):
            continue
        v = 2
        # v = get_speed(bot['player_state'])

        addTargetOnBot(bot)
        # bot['target'][1] = 10

        r = random(0, 4)
        ds = [(-v, 0), (v, 0), (0, -v), (0, v)]
        # dx, dy = ds[int(r)]
        dirs = lrud
        if bot['target']:
            col, row = bot['target'][0], bot['target'][1]
        botx_grid, boty_grid = get_grid_idx(bot['position'].x, bot['position'].y)
        p = (botx_grid, boty_grid)

        objs_nearby = find_nearest_obj(p, 4, position_object)
        bubbls = find_boom_place(p, 2, bubble_time)

        bricks = get_obs()

        if len(bubbls) > 0:

            bubble = bubbls[0]
            safes_ = find_nearest_safe(p, bubble, 2)

            if len(bubbls) > 1:
                for bubble in bubbls:
                    safes = find_nearest_safe(p, bubble, 2)
                    safes_ = [u for u in safes if u in safes_]

            safes = [s for s in safes_ if s not in bricks and s != bubble]
            if len(safes) > 0:
                safe = safes[0]

                if (botx_grid, boty_grid) in bricks:
                    print('on brick')
                elif safe in bricks:
                    print('safe on brick')
                # if (botx_grid, boty_grid) ==safe:
                #     continue
                r = get_dir(bot, botx_grid, boty_grid, safe)
                if r is not None:
                    bot['player_state']['current_direction'] = lrud[r]
                    dx, dy = ds[int(r)]

                    add_bot_mile(bot, v)
                    pp = bot['position']
                    bot_displacement(bot, dx, dy)
                else:
                    print('no r', r)
                continue

            else:
                print('no place to hide')
                continue
        # 有道具
        elif len(objs_nearby) > 0:

            safe = objs_nearby[0]

            r = get_dir(bot, botx_grid, boty_grid, safe)
            if r is not None:
                bot['player_state']['current_direction'] = lrud[r]
                dx, dy = ds[int(r)]
                add_bot_mile(bot, v)
                pp = bot['position']
                bot_displacement(bot, dx, dy)

            continue
        # 在 目标砖块旁边
        elif bot['target'] and is_neighbood((botx_grid, boty_grid), (col, row)) and not p in bubble_time:
            bot_put_bubble(bot, p)

            continue
        #
        elif bot['target']:

            # print('nothing')
            targety, targetx = get_grid_centre(row, col)

            # d = 1000000000
            # nearest = -1
            # datas = []
            # for i in range(len(dirs)):
            #     ds = [(-v, 0), (v, 0), (0, -v), (0, v)]
            #     dx, dy = ds[i]
            #     x2, y2 = (bot['position'].x + dx, bot['position'].y + dy)
            #     gx, gy = get_grid_idx(x2, y2)
            #     if (gx, gy) in bubble_time or (gx, gy) in position_brick['gongfu']:
            #         continue
            #     r2 = (targety - y2) ** 2 + (targetx - x2) ** 2
            #     if r2 < d:
            #         d = r2
            #         nearest = i
            #     datas.append((i, r2 ** 0.5))
            # datas = sorted(datas, key=lambda x: x[1])
            # if len(datas) == 0:
            #     #print('no direct')
            #     r = random(0, 4)
            # else:
            #     nearest = datas[0][0]
            #     if nearest != -1:
            #         r = nearest

            #     r  = nearest

            r = None

            if col >= 1:
                r = get_dir(bot, botx_grid, boty_grid, (col - 1, row))

            if r is None:
                r = get_dir(bot, botx_grid, boty_grid, (col + 1, row))

            if r is not None:
                bot['player_state']['current_direction'] = lrud[r]
                dx, dy = ds[int(r)]
                add_bot_mile(bot, v)
                bot_displacement(bot, dx, dy)

        elif bot_attract_other(p, bot, [b for b in bots if b != bot]):
            if random(0, 1) < 0.1:

                bot_put_bubble(bot, p)
            else:
                bot['walk_target'] = get_random_target(botx_grid, boty_grid)
        elif in_bot_attract_range(p, get_bot_power(bot), (mex, mey)):

            bot_put_bubble(bot, p)
        elif bot.get('walk_target'):

            r = get_dir(bot, botx_grid, boty_grid, bot['walk_target'])
            if r is not None:
                bot['player_state']['current_direction'] = lrud[r]
                dx, dy = ds[int(r)]
                add_bot_mile(bot, v)
                bot_displacement(bot, dx, dy)
            elif (botx_grid, boty_grid) == bot['walk_target']:
                bot['walk_target'] = get_random_target(botx_grid, boty_grid)
            else:

                bot['walk_target'] = get_random_target(botx_grid, boty_grid)
            # r = get_dir(botx_grid,boty_grid, target)
        elif not bot['target']:

            walk_target = get_random_target(botx_grid, boty_grid)
            if walk_target not in get_obs():
                bot['walk_target'] = walk_target

    obj_map = get_inverted_obj_map(position_object)
    for bot in bots:
        pV = bot['position']
        obj, bot_grid_p = is_player_on_obj_pv(pV, obj_map)
        if obj:
            bot_add_obj(bot, obj)
            del obj_map[bot_grid_p]
            position_object[obj].remove(bot_grid_p)


def try_boom_bots(boom_grid_pos):
    for bot in bots:
        pp = bot['position']
        gridx, gridy = get_grid_idx(pp.x, pp.y)
        if (gridx, gridy) == boom_grid_pos:
            bot['state'] = 'Dead!'


def trap_process(player_state, position):
    if player_state['player_state']['trap'] is True:
        if 'misc111_stand' not in player_state['player_state']:
            g = Gif(position.x, position.y, 'misc111_stand')
            g.tick_time = 250
            player_state['player_state']['misc111_stand'] = g
            g.is_loop = True
            g.start()
        g = player_state['player_state']['misc111_stand']
        image(g.get_current_frame(), position.x - 30, position.y - g.get_current_frame().height)
    else:
        if 'misc111_stand' in player_state['player_state']:
            del player_state['player_state']['misc111_stand']


tasks = []


def write_status_bar():
    textSize(20)
    for i, c in enumerate(['number', 'power', 'speed']):
        n = self_state['player_state']['obj'][c]
        fill(255)
        text(str(n), i * 50 + 50, 585)


# mainloop
def draw():
    # ui_state0
    if game_state['ui_state'] == '0':
        if not keyPressed:
            game_state['is_pressed'] = False
        image(imgs['selectRoom'], 0, 0)

        if game_state['bigIconNames_begin'] == []:
            bigIconNames_begin = [sample(bigIconNames) for i in range(8)]
            game_state['bigIconNames_begin'] = bigIconNames_begin
        show_top_btn()
        show_mode()
        show_room()
        show_bottom_btn()
    # ui_state4
    elif game_state['ui_state'] == '4':
        background(255)
        if 'edit_map' not in game_state:
            game_state['edit_map'] = 'machine01_6.map'
        mymap = game_state['edit_map']
        data_mymap = sampleMap.map_class[mymap]
        mode = mymap.split('_')[0][:-2]

        assert mode in imgs_elem
        for k in ['backMapElems', 'foreMapElems']:
            if not game_state['show_back'] and k == 'backMapElems':
                continue
            if not game_state['show_fore'] and k == 'foreMapElems':
                continue
            layer = data_mymap[k]

            # if k == 'backMapElems':
            #     continue
            for row in range(13):
                for col in range(14, -1, -1):
                    id = layer[row][col]

                    if id % 1000 not in imgs_elem[mode]:
                        continue
                    if id not in qqtMapElems:
                        print('missing ', id)
                        x, y = 0, 0
                    else:
                        x, y = qqtMapElems[id].offset
                    # img_one = img_cache[mode][id % 1000]
                    tile = imgs_elem[mode][id % 1000]
                    # noFill()
                    stroke(0)
                    fill(0, 50)
                    # grid_x,grid_y =  10+40*col  ,15+40* row
                    grid_x, grid_y = get_grid_topleft(col, row)
                    image(tile, grid_x - x, grid_y - y)
                    rect(grid_x, grid_y, 40, 40)
    # ui_state3
    elif game_state['ui_state'] == '3':
        # if not keyPressed :
        #     game_state['is_pressed'] = False
        # 编辑模式
        # ui_state=3
        # background(0,136,222)
        # draw_match_bg()
        background(255)

        global bgm
        global bgm2
        bgm.stop()
        bgm2.stop()
        position_object.update(
            {'number': [(2, 3), (5, 4), (5, 6)], 'speed': [(6, 6)], 'power': [(1, 5), (2, 6), (3, 6), (4, 6)]})
        for obj_name, positions in position_object.items():
            for x, y in positions:
                # - abs(int(millis() / 125) % 8 - 4) * 2
                x2, y2 = get_grid_topleft(x, y, (0, 0))
                if obj_name != 'power':
                    image(imgs[obj_name], x2 + 0.5 * (40 - imgs[obj_name].width),
                          y2)  # ,40, 40 * imgs[obj_name].height / imgs[obj_name].width)
                else:
                    image(imgs[obj_name], x2 + 0.5 * (40 - imgs[obj_name].width), y2 + 40 - imgs[obj_name].height)
        for row in range(13):
            for col in range(15):
                stroke(0)
                noFill()
                # 40 * 40
                rect(col * 40, row * 40, 40, 40)
        for px, py in sorted(build_map.keys()):
            v = build_map[(px, py)]
            # x, y = get_square_grid_topleft(px,py,game_zone)
            x, y = get_grid_topleft(px, py, (0, 0))
            # 绘制
            if v not in imgs_elem['bun']:
                continue
            if imgs_elem['bun'][v] is None:
                continue
            print(x, y, y + 40 - imgs_elem['bun'][v].height)
            image(imgs_elem['bun'][v], x, y + 40 - imgs_elem['bun'][v].height)
        padding = 0
        for i in range(13):
            if i == 0:
                continue
            fill(0)
            # 键位
            text(list('qwertyuiopasdfg')[i], padding + 10, 535)
            # 绘制
            image(imgs_elem['bun'][i], padding, 540)
            line(padding, 530, padding, 550)
            padding += imgs_elem['bun'][i].width
        if 'state2' in tasks:
            tasks.remove('state2')


    # ui_state2
    elif game_state['ui_state'] == '2':
        global global_map_data
        # game start
        if not keyPressed:
            game_state['is_pressed'] = False
        background(0, 136, 222)
        if bgm.isPlaying():
            bgm.stop()
        global bgm2
        if not bgm2.isPlaying():
            bgm2.play()
        # draw_match_bg()
        # image(imgs['bgGame']  ,0,0)
        if self_state['state'] == 'alive' and not all([not is_bot_alive(bot) for bot in bots]):

            # cur_map = map_match02.copy()#{(5, 5): 2, (8, 5): 2, (10, 5): 2}
            # imgs_elem['match'][i]
            map_k = ''
            mapi = game_state['current_map_i']
            mode = map_mode_list[mapi]

            if 'state2' in event_queue:

                position_object_ = {'number': [], 'speed': [], 'power': []}
                position_object.update(position_object_)
                for k, mapdict in map_class.items():
                    if map_mode_list[mapi] + '01' in k:
                        mymap = k
                print('state2 init runs')
                global_map_data = make_map_copy(sampleMap.map_class, mymap)
                # global_map_data =d# sampleMap.map_class[mymap].copy()
                game_state['map_mode'] = mymap.split('_')[0][:-2]
                event_queue.remove('state2')
                set_born_point(bots)

            mode = game_state['map_mode']

            assert mode in imgs_elem
            for k in ['backMapElems', 'foreMapElems']:
                if not game_state['show_back'] and k == 'backMapElems':
                    continue
                if not game_state['show_fore'] and k == 'foreMapElems':
                    continue
                layer = global_map_data[k]
                for row in range(13):
                    for col in range(14, -1, -1):
                        id = layer[row][col]

                        if id % 1000 not in imgs_elem[mode]:
                            continue
                        if id not in qqtMapElems:
                            print('missing ', id)
                            x, y = 0, 0
                        else:
                            x, y = qqtMapElems[id].offset
                        # img_one = img_cache[mode][id % 1000]
                        tile = imgs_elem[mode][id % 1000]
                        # noFill()
                        stroke(0)
                        fill(0, 50)
                        # grid_x,grid_y =  10+40*col  ,15+40* row
                        grid_x, grid_y = get_grid_topleft(col, row)
                        image(tile, grid_x - x, grid_y - y)
                        # rect(grid_x,grid_y,40,40)

            for obj_name, positions in position_object.items():
                for x, y in positions:
                    x2, y2 = get_grid_topleft(x, y)
                    image(imgs[obj_name], x2, y2 - imgs[obj_name].height * 0.5 - abs(int(millis() / 125) % 8 - 4) * 2,
                          40, 40 * imgs[obj_name].height / imgs[obj_name].width)
            obj_map = get_inverted_obj_map(position_object)
            obj, bot_grid_p = is_player_on_obj((me.x, me.y), obj_map)
            if obj:
                bot_add_obj(self_state, obj)
                del obj_map[bot_grid_p]
                position_object[obj].remove(bot_grid_p)
            user_control()
            # 泡泡对象
            for b in my_state.get('bubbles_obj', []):
                # if not b or millis()/1000 > b.get_effect_end_time():continue

                cur_time = millis() / 1000
                all_people = [self_state] + bots
                bricks = get_current_obs()  # global_map.keys()
                hitted_players, all_hitted_brick = b.wait_or_explode(all_people, bricks, cur_time, image, get_grid_idx)
                for p in hitted_players:
                    p['player_state']['trap'] = True
                # 炸砖块
                for brick in all_hitted_brick:
                    new_obj(position_object, brick)

                remove_current_obs(all_hitted_brick)

            # 边界limit
            me.x, me.y = limit_player(me.x, me.y)
            if self_state['player_state']['trap'] is True:
                if 'misc111_stand' not in self_state['player_state']:
                    g = Gif(me.x, me.y, 'misc111_stand')
                    g.tick_time = 250
                    self_state['player_state']['misc111_stand'] = g

                    g.is_loop = True

                    g.start()
                g = self_state['player_state']['misc111_stand']
                image(g.get_current_frame(), me.x - 30, me.y - g.get_current_frame().height)
            else:
                if 'misc111_stand' in self_state['player_state']:
                    del self_state['player_state']['misc111_stand']

            if 'misc111_stand' not in gif_obj_cache:
                gif_obj_cache['misc111_stand'] = Gif(me.x, me.y, 'misc111_stand')
                gif_obj_cache['misc111_stand'].start()
            if 'timer' not in game_state:
                game_state['timer'] = Timer()

            mex, mey = get_grid_idx(me.x, me.y)
            for bot in bots:
                is_dead = False
                if bot['player_state']['trap'] is True:
                    if 'jail' not in bot:
                        bot['jail'] = Jail(bot['position'].x, bot['position'].y, millis() / 1000, bot['id'], bot)
                    is_dead = bot['jail'].wait_or_explode(millis() / 1000)
                    print('is_dead', is_dead)
                if is_dead or (bot != self_state and bot['player_state']['trap'] is True):

                    botx_grid, boty_grid = get_grid_idx(bot['position'].x, bot['position'].y)
                    if (mex, mey) == (botx_grid, boty_grid) or is_dead:
                        bot['state'] = 'Dead!'
                        bot['player_state']['trap'] = False
                        resource_sound['attrack'].play()
                    continue
            is_dead = False
            if self_state['player_state']['trap'] is True:
                if 'jail' not in self_state:
                    self_state['jail'] = Jail(self_state['pos'].x, self_state['pos'].y, millis() / 1000, -1, self_state)
                is_dead = self_state['jail'].wait_or_explode(millis() / 1000)
            killer = None
            if not is_dead and self_state['player_state']['trap']:
                for bot in bots:
                    botx_grid, boty_grid = get_grid_idx(bot['position'].x, bot['position'].y)
                    if (bot != self_state) and (mex, mey) == (botx_grid, boty_grid):
                        killer = bot
                        break

            if is_dead:
                self_state['state'] = 'Dead!'
                self_state['player_state']['trap'] = False
                resource_sound['attrack'].play()

                # bots_move()
            # 更新自己

            update_me(self_state)
            bots_moving_obj_dict[-1].show_image(image)
            for bot in bots:
                b = bot
                update_bot(bot)
                # if not bot['player_state']['trap']:
                bots_moving_obj_dict[bot['id']].show_image(image)
                if not is_bot_alive(bot):
                    fill(0, 200)
                    obj = bots_moving_obj_dict[bot['id']]
                    x_, y_ = obj.x - 30, obj.y - 60
                    rect(x_, y_, 50, 70)

                c, r = get_grid_idx(b['position'].x, b['position'].y)
                x_, y_ = get_grid_topleft(c, r)
                fill(255, 0, 0, 50)
                rect(x_, y_, 40, 40)
                # white
                fill(255, 20)
                rect(b['position'].x - 20, b['position'].y - 20, 40, 40)
                bot_p = bot['position']
                fill(0)
                text(str(bot['target']) + str(bot.get('walk_target', '/')), bot_p.x, bot_p.y - 40)
            for bot in bots:
                trap_process(bot, bot['position'])
        # ui_stateelse
        else:
            # fangjian 房间
            sound['bgm'].stop()
            game_state['timer'].stop()

            if bgm2.isPlaying():
                bgm2.stop()
            # if 'winbgm' in game_state:
            #     winbgm.play()
            #     game_state['winbgm'] = True
            textSize(30)
            fill(0)
            title = 'You Win!'
            if self_state['state'] == 'Dead!':
                title = 'You Lose'
                if losebgm.isPlaying() == False:
                    losebgm.play()
            else:
                if winbgm.isPlaying() == False:
                    winbgm.play()

            text(title, 0.3 * w - textWidth(title) * 0.5, 0.5 * h)
        for n in img_pos.keys():
            imgx, imgy = img_pos[n]
            image(imgs[n], imgx, imgy)
        # 离开游戏
        for n in ['leavegame', 'saveReplay']:
            # print(btn_cache[n].disable)
            btn_cache[n].show_with_mouse((mouseX, mouseY), mousePressed)

            # 离开游戏
        if btn_cache['leavegame'].isClicked and not keyPressed:
            for n in tasks:
                tasks.remove(n)

            btn_cache['leavegame'].isClicked = False

            if winbgm.isPlaying():
                winbgm.stop()
            tmp = new_self_state()
            self_state.update(tmp)
            self_state['pos'] = me
            self_state['pos'].x = 100
            self_state['pos'].y = 100
            # back to room
            game_state['ui_state'] = '1'
            n_bot = 1
            for b in bots:
                bots.remove(b)
            self_state['state'] = 'alive'
            for i in range(n_bot):
                bot = new_bot()
                bots.append(bot)
                bots_dict[bot['id']] = bot
                bot_obj = Moving.MovingObj(0, 0)
                bot_obj.register_walk_pic(bot_img)
                bots_moving_obj.append(bot_obj)
                bots_moving_obj_dict[bot['id']] = bot_obj
            for btn in room_buttons + room_start_return:
                btn.isClicked = False
            for b in bubble_time:
                del bubble_time[b]

            btn_cache['start'].isClicked = False
            # btn_cache['start'].disable = True
            global tmp_map_index
            tmp_map_index = -1

        write_status_bar()
        stroke(255)
        line(800 - 184, 0, 800 - 184, 600)
        noStroke()
        for row in range(8):
            fill(172, 218, 244)
            rect(800 - 184 + 7, 106 + row * 51, 25, 47)
        if 'timer' in game_state:
            game_state['timer'].show_game_time()
    # lobby
    elif game_state['ui_state'] == '1':
        if not keyPressed:
            game_state['is_pressed'] = False
        image(imgs['bgRoom'], 0, 0)
        show_top_btn()
        show_player_section()
        if bgm2.isPlaying():
            bgm2.stop()
        if bgm.isPlaying() is False:
            bgm.play()

        # 游戏设置
        names = ['selMode', 'roomProp', 'selMap']
        # for i,ui_name in enumerate(names):
        #     img = imgs[ui_name]
        #     image(img,526,60+ i * 38)
        # 3个按钮
        for btn in room_buttons:
            # btn.draw_img(btn.get_image())
            if menu_state['state'] == '':
                btn.show_with_mouse((mouseX, mouseY), mousePressed)
            else:
                btn.draw_img(btn.get_image())
            # debug show
        # fill(0)
        # rect(me.x,me.y,40,40)
        # fill(255,100)
        # c,r = get_grid_idx(me.x,me.y)
        # x2,y2 = get_grid_topleft(c,r)
        # fill(255)
        # rect(x2,y2,40,40)

        # 我的背包
        image(imgs['storage'], bag_x, bag_y)
        # for btn in room_start_return:
        #     btn.show_with_mouse((mouseX,mouseY),mousePressed)

        # 开始 和 返回  键
        for n in ['start', 'return']:
            btn = btn_cache[n]
            if menu_state['state'] == '':
                btn.show_with_mouse((mouseX, mouseY), mousePressed)
            else:
                btn.draw_img(btn.get_image())

        player_i = game_state['player']
        update_me(self_state)
        bots_moving_obj_dict[-1].show_image(image)
        # walk_pic = player_walk[player_i]
        # 绘制泡泡

        # ui
        # 选地图的时候 不显示
        global tmp_map_index
        if game_state.get('clicked_menu_map_mode'):
            p = map_mini_pos
            image(imgs_map[game_state.get('clicked_menu_map_mode') + '01'], p[0], p[1])

        for rect_ in RectButton_cache.values():
            rect_.update_with_mouse((mouseX, mouseY), mousePressed)
            rect_.isClicked = False
        if 'next_page' in event_queue:
            game_state['page_number'] += 1
            game_state['page_number'] = min(3, game_state['page_number'])
            event_queue.remove('next_page')
        elif 'last_page' in event_queue:
            game_state['page_number'] -= 1
            game_state['page_number'] = max(1, game_state['page_number'])
            event_queue.remove('last_page')
        # 选人界面
        data = [None] + "1_mm|2_as|3_wk|4_tt|5_xq|6_cl|7_bbl|8_hy".split('|')
        px, py = (548, 212)
        if game_state['page_number'] == 1:
            Characters_ = chara_page1
        elif game_state['page_number'] == 2:
            Characters_ = chara_page2
        elif game_state['page_number'] == 3:
            Characters_ = chara_page3
        clicked_c = None
        for chara in Characters_:
            if chara:
                chara.show_with_mouse((mouseX, mouseY))
                if menu_state['state'] == '':
                    clicked = chara.update_with_mouse((mouseX, mouseY), mousePressed)
                    if clicked:
                        clicked_c = chara
        if clicked_c:
            for chara2 in Characters_:
                if not chara2: continue
                if menu_state['state'] == '':
                    if chara2 != clicked_c:
                        chara2.isClicked = False

        chara_name = game_state['character_py']

        user_gifs = player_walk[chara_name]
        bots_moving_obj_dict[-1].register_walk_pic(user_gifs)

        # 显示3个按钮
        # dlg_selMap_0_0.png

        for btn in room_buttons:

            # btn.draw_img(btn.get_image())

            if btn.img_name == 'selMap':
                if btn.isClicked and not keyPressed:
                    if menu_state['state'] == '':
                        menu_state['state'] = 'selMap'

                    # 地图
                    image(imgs_dlg['selMap'], map_sel_topleft[0], map_sel_topleft[1])
                    # 选择地图按钮
                    for btn in room_start_return:
                        if menu_state['state'] != '':

                            btn.show_with_mouse((mouseX, mouseY), mousePressed)
                        else:
                            btn.draw_img(btn.get_image())

                    fill(255)
                    x, y = map_sel_item_topleft

                    click_i, click_n = -1, ''
                    for i, n in enumerate(map_mode_list):
                        if n not in btn_cache: continue
                        if n == 'desert':
                            break

                        btn_cache[n].show_with_mouse((mouseX, mouseY), mousePressed)
                        if btn_cache[n].isClicked and not keyPressed:
                            click_n = n
                            click_i = i
                            for j, n_ in enumerate(map_mode_list):
                                if n_ != n:
                                    btn_cache[n_].isClicked = False

                    if click_i > -1:
                        item_i = click_i
                        fill(0, 100)
                        global tmp_map_index
                        tmp_map_index = item_i

                        game_state['clicked_menu_map_mode'] = map_mode_list[item_i]
                        rect(x, y + item_i * 34, 115, 34)

        x, y = map_sel_item_topleft

        if room_start_return[-1].isClicked and not keyPressed:
            # 返回
            # 选择地图取消
            room_buttons[-1].isClicked = False
            room_start_return[-1].isClicked = False
            game_state['current_map'] = ''
            menu_state['state'] = ''
            tmp_map_index = -1
        elif room_start_return[0].isClicked and not keyPressed:
            menu_state['state'] = ''
            room_start_return[0].isClicked = False

            room_buttons[-1].isClicked = False
            if tmp_map_index != -1:
                game_state['current_map'] = 'match0' + str(tmp_map_index + 1)
                btn_cache['start'].disable = False
                game_state['current_map_i'] = tmp_map_index
            tmp_map_index = -1
        elif btn_cache['start'].isClicked and not keyPressed:

            # 开始键
            print('press start game')
            game_state['ui_state'] = '2'
            tmp_map_index = -1
            if 'state2' not in event_queue:
                print('from1 to 2 add state2 init')
                event_queue.append('state2')
            for b in bubble_time:
                del bubble_time[b]
            if 'timer' not in game_state:
                game_state['timer'] = Timer()


        elif btn_cache['return'].isClicked and not keyPressed:
            btn_cache['return'].isClicked = False
            print('to lobby  e')
            for b in bubble_time:
                del bubble_time[b]
            game_state['ui_state'] = '0'
            tmp_map_index = -1
            game_state['bigIconNames_begin'] = []

        user_control()

        for b in my_state.get('bubbles_obj', []):
            cur_time = millis() / 1000
            b.wait_or_explode([self_state] + bots, get_obs(), cur_time, image, get_grid_idx)
            # b.wait_or_explode(millis()/1000,image)


def mousePressed():
    pass


def mouseClicked():
    x, y = map_sel_item_topleft


def add_bubble(x, y):
    if not is_chara_has_bubble(my_state):
        return
    x_, y_ = get_grid_idx(x, y, zone_topleft=game_zone)
    if (x_, y_) not in my_state['bubbles'] and (x_, y_) not in bubble_time:
        my_state['bubbles'].append((x_, y_))
        add_bubble_radius((x_, y_), get_power(self_state))

        bubble_time[(x_, y_)] = millis()
        flame_gif_index[(x_, y_)] = 0


def add_bubble_obj(x, y):
    x_, y_ = get_grid_idx(x, y, zone_topleft=game_zone)
    if 'bubbles_obj' not in my_state:
        my_state['bubbles_obj'] = []
    for b in my_state['bubbles_obj']:
        if b.is_time_after_effect(millis() / 1000):
            my_state['bubbles_obj'].remove(b)
    for b in my_state['bubbles_obj']:

        if (b.x, b.y) == (x_, y_):
            return
    global bubble_current_id
    b = Bubble(x_, y_, 3, millis() / 1000, bubble_current_id, Gif, get_grid_topleft)
    bubble_current_id += 1
    # b.grid2topleft = get_grid_topleft
    b.create_and_set_gif_and_start(Gif)
    my_state['bubbles_obj'].append(b)


def limit_player(x, y):
    left, top = game_zone
    return max(min(x, left + 15 * grid_w - 20), left + 20), max(min(y, top + 13 * grid_h - 20), top + 20)


def brick_bubble_player_limit(pp, direction, mapElem, pass_wall=False):
    if self_state['player_state']['trap']:
        return pp
    v = get_speed(self_state)
    c, r = get_grid_idx(pp.x, pp.y)
    forbids = bubble_time.keys() + mapElem  # + position_brick['gongfu'] + position_brick['box']
    charcter_body_width = 20
    grid_cell_size = 20
    interval = charcter_body_width + grid_cell_size
    is_limit = False
    dir2dxdy = {'left': (-1, 0), 'right': (1, 0), 'up': (0, -1), 'down': (0, 1)}
    dx, dy = dir2dxdy[direction]
    if game_state['ui_state'] != '2' or pass_wall:
        pp.x = pp.x + dx * v
        pp.y = pp.y + dy * v

        return pp
    if direction == 'left':
        if (c - 1, r) in forbids:
            col, row = (c - 1, r)
            cell_x_mid, cell_y_mid = get_grid_centre(col, row, zone_topleft=game_zone)
            pp.x = max(pp.x + dx * v, cell_x_mid + interval)
            is_limit = True
    elif direction == 'right':
        if (c + 1, r) in forbids:
            col, row = (c + 1, r)
            cell_x_mid, cell_y_mid = get_grid_centre(col, row, zone_topleft=game_zone)
            pp.x = min(pp.x + dx * v, cell_x_mid - interval)
            is_limit = True

    elif direction == 'up':
        if (c, r - 1) in forbids:
            col, row = (c, r - 1)
            cell_x_mid, cell_y_mid = get_grid_centre(col, row, zone_topleft=game_zone)
            pp.y = max(pp.y + dy * v, cell_y_mid + interval)
            is_limit = True
    elif direction == 'down':
        if (c, r + 1) in forbids:
            col, row = (c, r + 1)
            cell_x_mid, cell_y_mid = get_grid_centre(col, row, zone_topleft=game_zone)
            pp.y = min(pp.y + dy * v, cell_y_mid - interval)
            is_limit = True

    if is_limit:
        pass

    else:
        pp.x = pp.x + dx * v
        pp.y = pp.y + dy * v
    return pp


def me_move(me, k2dv, presskey):
    me.x += k2dv[presskey][0]
    me.y += k2dv[presskey][1]


def keyReleased():
    # if isinstance(key, unicode) is False:
    #     print('not str key', key, type(key))
    #     return
    if game_state['ui_state'] in ['3']:
        return
    if key == CODED:
        if keyCode in [37, 38, 39, 40]:
            keycode2key = {38: 'w', 39: 'd', 40: 's', 37: 'a'}
            current_key = keycode2key[keyCode]
            key_hold.remove(current_key)

        return

    if key in list('asdw'):
        key_hold.remove(key)


def keyPressed():
    if key == 'm' and mousePressed:
        print('x,and y ', mouseX, mouseY)
    # if isinstance(key, unicode) is False:
    #     print('not str key', key, type(key))
    #     return
    # 地图编辑器
    if game_state['ui_state'] in ['4']:
        # p =  get_grid_idx(mouseX,mouseY,zone_topleft =game_zone)

        p = get_grid_idx(mouseX, mouseY, zone_topleft=(0, 0))
        # all_key = list('qwertyuiopasdfghjk')
        # if key in all_key:
        #     i = all_key.index(key)
        #     build_map[p] = i

        # if key == 'q':
        #     build_map[p] = 2
        # if key == 'e':
        #     build_map[p] = 3
        if key == 'z':
            if p in build_map:
                del build_map[p]
        if key == 'l':
            print('\n\n')

            build_map_ = {str(k): v for k, v in build_map.items()}

            # saveBytes("build_map.txt", [1, 2, 3] * 50)
        if key == 'o':
            game_state['show_back'] = not game_state['show_back']
        if key == 'p':
            game_state['show_fore'] = not game_state['show_fore']
        if key in list('xcvbn'):
            i = 'xcvbn'.index(key)
            maplist = ['machine01_6.map', 'treasure01_4.map', 'box01_8.map', 'tank01_8.map', 'sculpture01_8.map',
                       'desert01_4.map', 'mine01_4.map', 'match01_2.map', 'bun01_8.map', 'bomb01_8.map', 'pig01_4.map',
                       'snow01_4.map', 'field01_4.map', 'water01_4.map', 'town01_4.map']
            game_state['edit_map'] = maplist[i + 6]

        return
    if key == CODED:
        if keyCode in [37, 38, 39, 40]:
            keycode2key = {38: 'w', 39: 'd', 40: 's', 37: 'a'}
            current_key = keycode2key[keyCode]
            if current_key not in key_hold:
                key_hold.append(current_key)
        return

        #   切换选人界面
    if key == 'k':
        if game_state['page_number'] == 1:
            game_state['page_number'] = 2
        else:
            game_state['page_number'] = 1
    # 解救自己
    if self_state['player_state']['trap']:
        if key == '3':
            self_state['player_state']['trap'] = False
            if 'misc111_stand' in self_state['player_state']:
                del self_state['player_state']['misc111_stand']
    else:
        if key in ['0', '1', '2', '3']:
            game_state['ui_state'] = key
    # 按i测试trap
    if key == 'i':
        self_state['player_state']['trap'] = True

    # 正常放炮和远程放炮
    if game_state['ui_state'] in ['1', '2']:
        if key == 'j' or key == ' ':
            add_bubble_obj(me.x, me.y)

    # 控制方向
    if key in list('asdw'):
        if key not in key_hold:
            key_hold.append(key)